package com.rd.p2p.app.user;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.Action;

import com.opensymphony.xwork2.ModelDriven;
import com.qdlc.p2p.biz.model.AppUserModel;
import com.qdlc.p2p.biz.service.UserCacheService;
import com.qdlc.p2p.biz.service.UserLoginService;
import com.qdlc.p2p.biz.service.UserService;
import com.qdlc.p2p.biz.service.user.ResetPasswordStepModel;
import com.qdlc.p2p.biz.service.user.UserPasswordService;
import com.qdlc.p2p.biz.service.user.UserPayPasswordService;
import com.qdlc.p2p.biz.service.user.UserRegistService;
import com.qdlc.p2p.biz.util.NoticeTemplateSender;
import com.qdlc.p2p.biz.util.UserLoginUtil;
import com.qdlc.p2p.biz.util.UserReturnResult;
import com.qdlc.p2p.biz.util.ValidCodeSender;
import com.qdlc.p2p.biz.util.ValidateUtil;
import com.qdlc.p2p.biz.util.mail.Mail;
import com.qdlc.p2p.biz.web.action.BaseAction;
import com.qdlc.p2p.common.constant.Constant;
import com.qdlc.p2p.common.constant.NoticeTplNid;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.exception.BusinessException;
import com.qdlc.p2p.common.exception.UserException;
import com.qdlc.p2p.common.util.DataUtils;
import com.qdlc.p2p.common.util.HttpRequestUtil;
import com.qdlc.p2p.common.util.MessageCheck;
import com.qdlc.p2p.common.util.OrderNoUtils;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.dal.checkrule.LoginRuleCheck;
import com.qdlc.p2p.dal.checkrule.SafetyRuleCheck;
import com.qdlc.p2p.dal.common.RuleCheckHelper;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.model.UserModel;

public class AppUserAction extends BaseAction<AppUserModel> implements ModelDriven<AppUserModel> {

	@Resource
	private UserService userService;
	@Resource
	private UserCacheService userCacheService;
	@Resource
	private UserPayPasswordService userPayPasswordService;
	@Resource
	private UserLoginService userLoginService;
	@Resource
	private UserPasswordService userPasswordService;
	@Resource
	private UserRegistService userRegistService;

	private static final String SESSION_REGIST_USER_MODEL = "regist_user_model";

	/** 平台安全性规则 **/
	private SafetyRuleCheck safetyRuleCheck = RuleCheckHelper.getValue(SafetyRuleCheck.class);

	private Map<String, Object> data;

	/**
	 * 判断用户名是否已存在
	 * 
	 * @throws Exception
	 */
	@Action(value = "/app/user/checkUsername")
	public void checkUsername() throws Exception {
		try {
			safetyRuleCheck.hasFontUnallowedUsername(model);
		} catch (Exception e) {
			printWebResCodeAndMsgResult("0", e.getMessage());
			return;
		} // 安全规则-禁止使用敏感用户名
		int count = userService.countByUserName(model.getUserName());
		data = model.checkUsernameResponse(count);
		printWebJson(getStringOfJpaObj(data));
	}

	/**
	 * 判断邮箱是否已被使用
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "/app/user/checkEmail")
	public void checkEmail() throws Exception {
		data = model.validEmail();
		if (StringUtil.isBlank(data)) {
			int count = userService.countByEmail(model.getEmail());
			data = model.checkEmailResponse(count);
			printWebJson(getStringOfJpaObj(data));
		} else {
			printWebJson(getStringOfJpaObj(data));
		}
	}

	/**
	 * 判断身份证号码是否已被使用
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "/app/user/checkCardId")
	public void checkCardId() throws Exception {
		data = model.validCardId();
		if (StringUtil.isBlank(data)) {
			int count = userService.countByCardId(model.getCardId());
			data = model.checkCardIdResponse(count);
			printWebJson(getStringOfJpaObj(data));
		} else {
			printWebJson(getStringOfJpaObj(data));
		}
	}

	/**
	 * 判断手机号码是否已被使用
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action(value = "/app/user/checkMobilePhone")
	public void checkMobilePhone() throws Exception {
		data = model.validMobilePhone();
		if (StringUtil.isBlank(data)) {
			int count = userService.countByMobilePhone(model.getMobilePhone());
			data = model.checkMobilePhoneResponse(count);
			printWebJson(getStringOfJpaObj(data));
		} else {
			printWebJson(getStringOfJpaObj(data));
		}
	}

	/**
	 * <p>登录</p>
	 * @author 原系统 2016年1月11日 下午12:49:33
	 * @throws Exception
	 * @modificationHistory=========================逻辑或功能性重大变更记录
	 * @modify by user: {Kaiju Zhao} 2016年1月11日 下午12:49:33
	 * @modify by reason:{方法名}:{APP使用Cookie有问题，将用户登录错误的次数放到session中供APP使用}
	 */
	@Action(value = "/app/user/doLogin")
	public void doLogin() throws Exception {
		data = new HashMap<String, Object>();
		User u = new User();
		boolean isPost = HttpRequestUtil.isPostMethod(request);
		if(!isPost){
			printWebResult("非法登录!", false);
		}
		// 联合登录用户
		User openUser = (User) request.getAttribute("openUser");
		if ((openUser != null) && (openUser.getUserName() != null)) {
			u = openUser;
			printWebResCodeAndMsgResult("1","登录成功");
			return;
		}
		// 获取请求参数
		UserModel userModel = new UserModel();
		userModel.setUserName(model.getUserName());
		userModel.setPwd(model.getPwd());
		String validCode = request.getParameter("validCode");
		if(validCode != null) {
			userModel.setValidCode(validCode);
		}

		//处理登录流程
		ReturnResult result = userLoginService.doLogin(userModel);
		if(result instanceof UserReturnResult){
			User user = ((UserReturnResult)result).getUser();
			loginSuccess(user, result);
		}

		//返回页面消息
		printWebResult(result.getErrorInfo(), result.isSuccess(), result.getExtra());
	}

	/**
	 * <p>退出</p>
	 * @author 原系统 2016年1月11日 下午4:17:29
	 * @throws Exception
	 * @modificationHistory=========================逻辑或功能性重大变更记录
	 * @modify by user: {Kaiju Zhao} 2016年1月11日 下午4:17:29
	 * @modify by reason:{方法名}:{增加将session中的错误登录次数清空的逻辑}
	 */
	@Action("/app/user/logout")
	public void logout() throws Exception {
		UserLoginUtil.cleanLoginUser();
		session.remove(Constant.SESSION_USER);
		data = new HashMap<String, Object>();
		data.put("result", true);
		data.put("msg", "登出成功！");
		printWebJson(getStringOfJpaObj(data));
	}

	/**
	 * 邮箱激活 重新发送激活邮件
	 * 
	 * @return
	 * @throws Exception
	 */
	@Action("/app/user/sentActivationEmail")
	public String sentActivationEmail() throws Exception {
		if ((model == null) || (model.getUserId() == 0)) {
			throw new UserException("用户不存在，激活邮件发送失败！", 1);
		}
		NoticeTemplateSender.newInstance(model, NoticeTplNid.NOTICE_EMAIL_ACTIVE)
			.addSendData("activeUrl", "/user/doRegisterStep1.html?id=" + Mail.getInstance().getdecodeIdStr(model))
			.send();
		printWebSuccess();
		return null;
	}

	@Action("/app/user/getPwdCode")
	public void getPwdCode() throws Exception {
		String email = paramString("email");
		String mobilePhone = paramString("mobilePhone");
		if(!StringUtils.isBlank(email)){
			User user = userService.getUserByEmail(email);
			ValidCodeSender.newInstance().sendCodeByEmail(user, email, NoticeTplNid.NOTICE_GET_PWD_EMAIL);
		}else if(!StringUtils.isBlank(mobilePhone)){
			User user = userService.getUserByMobilePhone(mobilePhone);
			ValidCodeSender.newInstance().sendCodeByEmail(user, mobilePhone, NoticeTplNid.NOTICE_GET_PWD_PHONE);
		}
		printWebSuccess();
	}

	/**
     * 找回密码
     *
     * @return
     * @throws Exception
     */
    @Action("/app/user/getpwd")
    public void getPwd() throws Exception {
		//如果请求有showType参数，则判断是哪种找回方式
		int showType = paramInt("showType");
		resetStep();
    }

	private String resetStep() throws Exception{

		//如果请求有getType，则判断以那种方式重置密码
		int strategyType = paramInt("getType");
		int step = paramInt("step");
		String keyWorlds = "";
		if(strategyType == ResetPasswordStepModel.RESET_PASSWORD_STRATEGY_TYPE_PHONE){
			keyWorlds = paramString("mobilePhone");
		}else if(strategyType == ResetPasswordStepModel.RESET_PASSWORD_STRATEGY_TYPE_EMAIL){
			keyWorlds = paramString("email");
		}

		//获取重置密码步骤数据模型
		ResetPasswordStepModel stepModel = new ResetPasswordStepModel(step, keyWorlds, strategyType);
		stepModel.setRequest(request);

		//收集每个步骤的参数
		if(step == ResetPasswordStepModel.STEP_1){
			String validCode = paramString("valicode");
			stepModel.setValidCode(validCode);
		}
		if(step == ResetPasswordStepModel.STEP_2){
			String code = paramString("code");
			stepModel.setCode(code);
		}
		if(step == ResetPasswordStepModel.STEP_3){
			String newPassword = paramString("pwd");
			String confirmNewPassword = paramString("confirmNewPwd");
			stepModel.setNewPassword(newPassword);
			stepModel.setConfirmNewPassword(confirmNewPassword);
		}

		//执行请求步骤
		ReturnResult result = userPasswordService.resetPasswordByMobilePhone(stepModel);
		if(result.isError()){
			printWebResCodeAndMsgResult("0",result.getErrorInfo());
			return null;
		}else{
			printWebResCodeAndMsgResult("1","请求成功");
			 return null;
		}
	}
	
	/**
	 * 认证-修改登录密码
	 *
	 * @return
	 * @throws Exception
	 */
	@Action("/app/user/modifyPwd")
	public void modifyPwd() throws Exception {

		User user = getSessionUser();
		if (user == null) {
			printWebResult("用户尚未登录", false);
			return;
		}
		String oldPassword = paramString("pwd");
		String newPassword = paramString("newPwd");
		String confirmNewPassword = paramString("confirmNewPwd");
		ReturnResult result = userPasswordService.modifyPassword(user, oldPassword, newPassword, confirmNewPassword);
		printWebResult(result.getErrorInfo(), result.isSuccess());
	}

	/**
	 * 认证-修改交易密码
	 *
	 * @return
	 * @throws Exception
	 */
	@Action("/app/user/modifyPaypwd")
	public void modifyPaypwd() throws Exception {
		User user = getSessionUser();
		if (user == null) {
			printWebResCodeAndMsgResult("-1","用户尚未登陆");
			return;
		}
		String payPassword = paramString("payPwd");
		String newPayPassword = paramString("newPayPwd");
		String confirmNewPayPassword = paramString("confirmNewPayPwd");
		ReturnResult result = userPayPasswordService.modifyPayPassword(user, payPassword, newPayPassword, confirmNewPayPassword);

		String resCode = result.isSuccess()? "1":"0";
		String resMsg = result.isSuccess()? "修改成功":result.getErrorInfo();
		// 返回认证结果
		printWebResCodeAndMsgResult(resCode,resMsg);
	}
	
	/**
	 * 注册第一步
	 *
	 * @return
	 * @throws Exception
	 */
	@Action("/app/user/registerFirst")
	public void registerFirst() throws Exception {
		data = new HashMap<String, Object>();
        if (paramInt("agree") != 1) {
            throw new UserException("请阅读并同意服务协议！", BusinessException.TYPE_JSON);
        }
        //初始化
        UserModel userModel = UserModel.instance(model);
        userModel.setUserType(paramInt("userType"));
        userModel.setValidCode(paramString("validCode"));
        userModel.setConfirmNewPwd(paramString("confirmPassword"));

		//3. 基本信息检测
		ReturnResult checkResult = userRegistService.checkRegisterBaseInfo(userModel);

		if(checkResult.isError()){
			printWebResCodeAndMsgResult("0",checkResult.getErrorInfo());
			return;
		}

        //邀请人
        String inviteMobilePhone = paramString("inviteMobilePhone");
        if(StringUtils.isNotBlank(inviteMobilePhone)){
        	if(ValidateUtil.isPhone(inviteMobilePhone)){
        	 User inviteUser = userService.getUserByMobilePhone(inviteMobilePhone);
        	 userModel.setInviteUser(inviteUser);
        	}
        }

        //把初步填写的user信息存入session中
        session.put(SESSION_REGIST_USER_MODEL, userModel);
		//6. 写入下一步注册数据
		Map<String, Object> data = new HashMap<String, Object>(2);

		data.put("resCode","1");
		data.put("mobilePhone", model.getMobilePhone());
		data.put("remain", 0);
		writeSignToken(data);
	}
	
	/**
     * 进行用户注册第二步 
     *
     * @return
     * @throws Exception
     */
    @Action("/app/user/registerSecond")
    public void doRegisterSecond() throws Exception {
        data = new HashMap<String, Object>();
		//1. 检测Sign
		ReturnResult result = checkSignTokenAndUserModel();
		if(result.isError()){
			printWebResCodeAndMsgResult("0",result.getErrorInfo());
			return;
		}

		//2. 设置验证码和请求IP，开始注册流程
		UserModel userModel = (UserModel) result.getExtra(SESSION_REGIST_USER_MODEL);
		userModel.setCode(paramString("code"));
		try {
			result = userRegistService.doRegister(userModel, false);
		} catch (Exception e) {
			writeRegistFailure(userModel.getUserName(), e);
		}

		if(result instanceof UserReturnResult){
			removeToken();
			writeRegistSuccess((UserReturnResult)result);
		}else{
			writeRegistFailure(userModel.getUserName(), null);
		}
    }
    
    /**
     * 注册获取验证码
     *
     * @return
     * @throws IOException
     */
    @Action("/app/user/getPhoneCode")
    public void getPhoneCode() throws IOException {
        data = new HashMap<String, Object>();

		//1. 检测Sign
		ReturnResult result = checkSignTokenAndUserModel();
		if(result.isError()){
			printWebResCodeAndMsgResult("0",result.getErrorInfo());
			return;
		}

		//2. 开始发送注册短信
		UserModel userModel = (UserModel) result.getExtra(SESSION_REGIST_USER_MODEL);
		String mobilePhone = StringUtils.trimToEmpty(paramString("mobilePhone"));
		result = userRegistService.doSendValidCode(userModel, mobilePhone);
		if(result.isError()){
			printWebResCodeAndMsgResult("0",result.getErrorInfo());
			return;
		}

		data.put("resCode", "1");
		data.put("resMsg", "发送验证码成功");
		//3. 写入下一步Sign和Token
		writeSignToken(data);
    }

    /**
     * 重置交易密码-获取验证码
     *
     * @return
     * @throws Exception
     */
    @Action("/app/security/getPaypwdCode")
    public void getPaypwdCode() throws Exception {
        User user = getSessionUser();
        if(user == null){
			printWebResCodeAndMsgResult("-1","用户暂未登录");
			return;
        }
		MessageCheck messageCheck=new MessageCheck();
		messageCheck.mobileAdd(user.getMobilePhone());
		ReturnResult result = ValidCodeSender.newInstance().sendCodeByPhone(user, user.getMobilePhone(),
				NoticeTplNid.NOTICE_GET_PAYPWD);
		String resCode = result.isSuccess()? "1":"0";
		String resMsg = result.isSuccess()? "发送验证码成功":result.getErrorInfo();
		// 返回认证结果
		printWebResCodeAndMsgResult(resCode,resMsg);
		return;
    }

    /**
     * 重置交易密码
     *
     * @return
     * @throws Exception
     */
    @Action("/app/security/resetPaypwd")
    public void resetPaypwd() throws Exception {
        User user = getSessionUser();
        data = new HashMap<String, Object>();
        if(user == null){
			printWebResCodeAndMsgResult("-1", "用户暂未登录");
			return;
        }
		String code = paramString("code");
		String newPayPassword = paramString("newPayPwd");
		String confirmNewPayPassword = paramString("confirmNewPayPwd");
		ReturnResult result = userPayPasswordService.modifyResetPayPassword(user, code, newPayPassword, confirmNewPayPassword);
		String resCode = result.isSuccess()? "1":"0";
		// 返回认证结果
		printWebResCodeAndMsgResult(resCode,result.getErrorInfo());
    }

	/**
	 * 写入Sign和Token信息
	 */
	private void writeSignToken(Map<String, Object> extraMap) throws IOException{
		HashMap<String, Object> data = new HashMap<String, Object>();
		if(extraMap != null){
			data.putAll(extraMap);
		}
		String sign = OrderNoUtils.getSerialNumber();
		data.put("sign", sign);
		String token = StringUtil.getMd5Sign(sign);
		session.put("token", token);
		printWebJson(getStringOfJpaObj(data));
	}

	/**
	 * 用户登录成功后处理
	 * @param user
	 * @param result
	 */
	private void loginSuccess(User user, ReturnResult result){
		//放入微信登陆图片
		String avatarPicPath = userCacheService.getUserCache(user.getUserId()).getAvatarPicPath();
		avatarPicPath = avatarPicPath.replaceAll("-", ".");
		session.put("avatarPicPath", avatarPicPath);

		result.addExtra("result", true);
		result.addExtra("msg", "登录成功！");
		result.addExtra("userName", user.getUserName());
		result.addExtra("imgurl", "/avatar/" + user.getUserId() + ".jpg");
		result.addExtra("redirectURL", paramString("redirectURL"));
	}

	/**
	 * 1. 检测Sign和Token信息
	 * 2. 检测Session中UserModel
	 */
	private ReturnResult checkSignTokenAndUserModel(){

		//检测Sign和Token信息
		String sign = StringUtil.getMd5Sign(paramString("sign"));
		String token = DataUtils.toString(session.get("token"));
		if (!sign.equals(token)) {
			return new ReturnResult("非法提交!");
		}

		//检测Session中UserModel
		UserModel userModel = (UserModel) session.get(SESSION_REGIST_USER_MODEL);
		if (userModel == null) {
			return new ReturnResult("请确认注册信息是否正确!");
		}

		ReturnResult result = new ReturnResult();
		result.addExtra(SESSION_REGIST_USER_MODEL, userModel);

		return result;
	}

	/**
	 * 处理注册失败
	 * @param userName
	 * @param e
	 */
	private void writeRegistFailure(String userName, Exception e) throws Exception{
		printWebResCodeAndMsgResult("0","注册失败！");
	}

	/**
	 * 注册成功后删除Token
	 */
	private void removeToken(){
		session.remove("token");
	}

	/**
	 * 处理注册成功，注册成功后缓存登录用户，并跳转到主页面
	 * @param result
	 */
	private void writeRegistSuccess(UserReturnResult result) throws Exception{
		User user = result.getUser();
		UserLoginUtil.cacheLoginUser(user.getUserId());
		result.addExtra("redirectURL", "/app/member/main.html");
		printWebResCodeAndMsgResult("1","注册成功！");
	}
}
